package de.koller.aframe.util.misc;

import de.koller.oceanFramework.math.RVec3;
import de.koller.oceanFramework.util.ColorIntUtil;

public class ColorOperations {
	
	public static int lightColor( int textureColor, int ambient, int diffuse, int specular ) {
		int k = ColorIntUtil.add( ambient, diffuse );
		k = multColor( textureColor, k );
		return ColorIntUtil.add( k, specular );
	}
	
	public static int specularLight( RVec3 lightvector, RVec3 surfaceNormal, RVec3 eyeNormal, int materialColor, int lightColor, float shininess ) {
		//vec4 ISpecular = gl_LightSource[0].specular * pow(max(dot(Reflected, Eye), 0.0), gl_FrontMaterial.shininess) * gl_FrontMaterial.specular;
		//vec3 Reflected = normalize(reflect( -lightvec, normal)); 
		RVec3 reflect = lightvector.newInstance().negate().reflectExtern( surfaceNormal );
		float pow = (float)Math.pow( Math.max( RVec3.dot( reflect, eyeNormal ), 0f), shininess );
		int c = mult( lightColor, pow );
		c = multColor( c, materialColor );
		return c;
	}
	
	public static int diffuseLight( RVec3 lightvector, RVec3 surfaceNormal, int materialColor, int lightColor ) {
		//gl_LightSource[0].diffuse * max(dot(normal, lightvec), 0.0) * gl_FrontMaterial.diffuse;
		lightvector = lightvector.newInstance().normalize();
		surfaceNormal = surfaceNormal.newInstance().normalize();
		
		float dot = RVec3.dot( surfaceNormal, lightvector );
		int c = mult( lightColor, Math.max( dot, 0f ) );
		c = multColor( c, materialColor );
		return c;
	}

	public static int mult( int color, float factor ) {
		int a = ColorIntUtil.clampSegment( (int)(ColorIntUtil.getAValue( color ) * factor) );
		int r = ColorIntUtil.clampSegment( (int)(ColorIntUtil.getRValue( color ) * factor) );
		int g = ColorIntUtil.clampSegment( (int)(ColorIntUtil.getGValue( color ) * factor) );
		int b = ColorIntUtil.clampSegment( (int)(ColorIntUtil.getBValue( color ) * factor) );
		return ColorIntUtil.getIntColor( a, r, g, b );
	}
	
	public static int multWithoutAlpha( int color, float factor ) {
		int c = mult( color, factor );
		return ColorOperations.setA( c, ColorIntUtil.getAValue( color ) );
	}
	
	public static int multColor( int color, int colorFactor ) {
		int a = ColorIntUtil.clampSegment( (int)(ColorIntUtil.getAValue( color ) 
											   * ColorIntUtil.getAValueF( colorFactor ) ) );
		int r = ColorIntUtil.clampSegment( (int)(ColorIntUtil.getRValue( color ) 
											   * ColorIntUtil.getRValueF( colorFactor ) ) );
		int g = ColorIntUtil.clampSegment( (int)(ColorIntUtil.getGValue( color ) 
											   * ColorIntUtil.getGValueF( colorFactor ) ) );
		int b = ColorIntUtil.clampSegment( (int)(ColorIntUtil.getBValue( color ) 
											   * ColorIntUtil.getBValueF( colorFactor ) ) );
		return ColorIntUtil.getIntColor( a, r, g, b );
	}
	
	public static int maxComponent( int c1, int c2 ) {
		int a = Math.max( ColorIntUtil.getAValue( c1 ), ColorIntUtil.getAValue( c2 ) );
		int r = Math.max( ColorIntUtil.getRValue( c1 ), ColorIntUtil.getRValue( c2 ) );
		int g = Math.max( ColorIntUtil.getGValue( c1 ), ColorIntUtil.getGValue( c2 ) );
		int b = Math.max( ColorIntUtil.getBValue( c1 ), ColorIntUtil.getBValue( c2 ) );
		return ColorIntUtil.getIntColor( a, r, g, b );
	}
	
	public static int addComponent( int c1, int c2 ) {
		return ColorIntUtil.add( c1, c2 );
	}
	
	public static int[] getColorComponents( int c ) {
		return new int[] {
			ColorIntUtil.getAValue( c ),
			ColorIntUtil.getRValue( c ),
			ColorIntUtil.getGValue( c ),
			ColorIntUtil.getBValue( c ),
		};
	}
	
	public static int getColorWithComponents( int[] cc ) {
		return ColorIntUtil.getIntColor( cc[0], cc[1], cc[2], cc[3] );
	}
	
	public static int setA( int color, int a ) {
		return ColorIntUtil.getIntColor( 
				a, 
				ColorIntUtil.getRValue( color ), 
				ColorIntUtil.getGValue( color ), 
				ColorIntUtil.getBValue( color ) );
	}
	
	public static int setR( int color, int r ) {
		return ColorIntUtil.getIntColor( 
				ColorIntUtil.getAValue( color ), 
				r, 
				ColorIntUtil.getGValue( color ), 
				ColorIntUtil.getBValue( color ) );
	}
	
	public static int setG( int color, int g ) {
		return ColorIntUtil.getIntColor( 
				ColorIntUtil.getAValue( color ), 
				ColorIntUtil.getRValue( color ), 
				g, 
				ColorIntUtil.getBValue( color ) );
	}
	
	public static int setB( int color, int b ) {
		return ColorIntUtil.getIntColor( 
				ColorIntUtil.getAValue( color ), 
				ColorIntUtil.getRValue( color ), 
				ColorIntUtil.getGValue( color ), 
				b );
	}
}
